﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using Newtonsoft.Json;
using Geometry;
using ReBot.API;


namespace rebot
{
    [Rotation("Dark Power","Dupe", WoWClass.Priest, Specialization.PriestShadow, 20)]
    public class Dark_Power20 : CombatRotation
    {
        //------Settings Start
        [JsonProperty("Levitate? yes or no   ")]
        public bool levitate_player = false;
        
        //------Settings Finish

        //-------------------Talent bool
        public bool Desperate_Prayer = false;
        public bool Spectral_guise = false;
        public String AngelicBalwark = "Passive";
        public String Body_and_soul = "Passive";
        public bool Angelic_Feather = false;
        public bool Phantasm = false;
        public String Surge_of_Darkness = "Passive";
        public bool Mindbender = false;
        public bool Insanity_Talent = false;
        public bool Void_Tendrils = false;
        public bool Psychic_Scream = false;
        public String Dominate_Mind = "Not implemented";
        public String Twist_of_Fate = "Passive";
        public bool Power_Infusion = false;
        public bool Spirit_Shell = false;
        public bool Cascade_talent = false;
        public bool Divine_Star = false;
        public bool Halo_talent = false;
        public bool Clarity_of_Power = false;
        public bool Void_Entropy = false;
        public bool Auspicious_Spirits = false;
        //-------------------Talent bool end
        public enum PriestSpellIds
        {
            MINDSEAR = 48045
        }  

        public bool Debug = true;

        //Writes to log
        private void DebugWrite(string text)
        {
            if (Debug) API.Print(text);
        }
        public Dark_Power20()
        {
            //Tier 1 Talents Detected -----
            if (HasSpell(19236))//Desperate Prayer
            {
                Desperate_Prayer = true;
                DebugWrite("Desperate Prayer tier 1 = " + Desperate_Prayer);
            }
            else if (HasSpell(112833))//Spectual guise
            {
                Spectral_guise = true;
                DebugWrite("Specual guise Tier 1 = " + Spectral_guise);
            }
            //Tier 1 end
            //Tier 2 Detected ---------
            if (HasSpell(121536))//Angelic Feather
            {
                Angelic_Feather = true;
                DebugWrite("Angelic Feather tier 2 = " + Angelic_Feather);
            }
            else if (HasSpell(108942))//Phantasm
            {
                Spectral_guise = true;
                DebugWrite("Phantasm Tier 2 = " + Phantasm);
            }
            //Tier 2 end
            //Tier 3 Detected ----------
            if (HasSpell(123040))//Mindbender
            {
                Mindbender = true;
                DebugWrite("Mindbender Tier 3 = " + Mindbender);
            }
            else if (HasSpell(139139))//Insanity
            {
                Insanity_Talent = true;
                DebugWrite("Power Word: Solace Tier 3 = " + Insanity_Talent);
            }
            //Tier 3 end
            //Tier 4 Detected -------------
            if (HasSpell(108920))//Void Tendrils
            {
                Void_Tendrils = true;
                DebugWrite("Void Tendrils Tier 4 = " + Void_Tendrils);
            }

            //Tier 4 end
            //Tier 5 Detected -------------
            if (HasSpell(10060))//Power Infusion
            {
                Power_Infusion = true;
                DebugWrite("Power Infusion Tier 5 = " + Power_Infusion);
            }
            else if (HasSpell(109964))//Spirit Shell
            {
                Spirit_Shell = true;
                DebugWrite("Spirit Shell Tier 5 = " + Spirit_Shell);
            }
            //Tier 5 end
            //Tier 6 Detected -------------
            if (HasSpell(121135))//Cascade
            {
                Cascade_talent = true;
                DebugWrite("Cascade Tier 6 = " + Cascade_talent);
            }
            else if (HasSpell(110744))//Divine Star
            {
                Divine_Star = true;
                DebugWrite("Divine Star Tier 6 = " + Divine_Star);
            }
            else if (HasSpell(120517))//Halo
            {
                Halo_talent = true;
                DebugWrite("Halo Tier 6 = " + Halo_talent);
            }
            //Tier 6 end
            //Tier 7 Detected ------------
            if (HasSpell(155246))//Clarity of Power
            {
                Clarity_of_Power = true;
                DebugWrite("Clarity of Will Tier 7 = " + Clarity_of_Power);
            }
            else if (HasSpell(155271))//Auspicious Spirits
            {
                Auspicious_Spirits = true;
                DebugWrite("Saving Grace Tier 7 = " + Auspicious_Spirits);
            }
            //Tier 7 end
            if (Insanity_Talent == false || Clarity_of_Power == false)
            {
                API.PrintError("Talents not selected correctly, make sure Insanity and Clarity of Power are chosen");
                return;
            }
        }
        public override bool OutOfCombat()
        {
            if (Me.IsMounted)
            {
                DebugWrite("Paused while mounted");
                return false;
            }
            else
            {

                if (CastSelf("Power Word: Fortitude", () => !HasAura("Power Word: Fortitude"))) return true;
                if (CastSelf("Shadowform", () => !HasAura("Shadowform"))) return true;

                if (CurrentBotName == "Combat")
                {
                    List<PlayerObject> members = Group.GetGroupMemberObjects();
                    if (members.Count > 0 && !Me.IsMoving)
                    {
                        PlayerObject deadPlayer = members.FirstOrDefault(x => x.IsDead && x.DistanceSquared < 10 * 10);
                        if (Cast("Mass Resurrection", () => deadPlayer != null, deadPlayer)) return true;
                    }

                }
                if (levitate_player == true)
                {
                    if (CastSelf("Levitate", () => Me.FallingTime > 2 && !HasAura("Levitate"))) return true;

                    // Only use OnWaterMove Spell, if Navi target is not in water. Cancel buff if we have to dive
                    if (API.GetNaviTarget() != Vector3.Zero && HasSpell("Levitate"))
                    {
                        if (!API.IsNaviTargetInWater())
                        {
                            if (CastSelf("Levitate", () => Me.Race != WoWRace.Tauren && Me.IsSwimming && !HasAura("Levitate"))) return true;
                        }
                        else if (HasAura("Levitate"))
                            CancelAura("Levitate");
                    }
                }
                List<PlayerObject> groupmembers = Group.GetGroupMemberObjects();
                List<PlayerObject> Tanks = groupmembers.FindAll(x => x.IsTank && x.IsInCombatRangeAndLoS);
                PlayerObject Tank1 = Tanks.FirstOrDefault();

                if (Tank1 != null && Tank1.InCombat && Me.Target != null)
                {
                    if (CastPreventDouble("Power Word: Shield", () => !Tank1.HasAura("Weakened Soul") && Tank1.IsInCombatRangeAndLoS && !Tank1.IsDead, Tank1, 1000)) return true;
                }
                if (Me.Target != null && Me.HealthFraction <= 0.7 || Tank1 != null && Me.Target != null)
                {
                    Healer();
                    return true;
                }
                Cast("Shadow Word: Pain", () => Me.HealthFraction > 0.7 && Me.Target != null && Me.Target.IsEnemy && !Me.Target.IsDead);
                return false;

            }


            return base.OutOfCombat();
        }
        public override void Combat()
        {

            if (Me.IsChanneling && Me.ChannelingSpellID == (int)PriestSpellIds.MINDSEAR) return;
          
            
                if (!Target.IsEnemy || Me.InCombat && Me.IsTargetingMeOrPets == true || (CombatRole.Equals(CombatRole.DPS) && Me.Target == Me))
                {
                    Healer();
                }
                else
                {
                    DPS();
                }
                //Dummy zapping
                if (Target.DisplayId == 87761 || Target.DisplayId == 88288)
                {
                    DPS();
                }
            

            
        }
       
        public void Healer()
        {
            if (Desperate_Prayer == true)
            {
                DesperatePrayer();
            }
            if (CastSelfPreventDouble("Flash Heal", () => Me.HealthFraction <= 0.9)) return;
        }
    
        public bool DPS()
        {
           
            if (Me.IsChanneling && Me.ChannelingSpellID == (int)PriestSpellIds.MINDSEAR) return true; 
           
            if (CastSelf("Shadowform", () => !HasAura("Shadowform"))) return false;

            //SetFacing(Me.Target);
            

            //Cast("Silence", () => Target.IsCastingAndInterruptible());
            List<PlayerObject> members = Group.GetGroupMemberObjects();
            List<PlayerObject> GrpHeal1 = members.FindAll(x => x.HealthFraction <= 0.85 && x.IsInCombatRangeAndLoS && !x.IsDead);


             if (!Me.Target.IsEnemy || (Me.HealthFraction < 0.5 && Me.HealthFraction > Me.Target.HealthFraction))
            {
                Healer();
            }
             else if (Me.Target.IsEnemy && Me.HealthFraction > 0.5 || Me.Target.IsAttackable)
             {
                 Cast("Mind Blast", () => Me.GetPower(WoWPowerType.PriestShadowOrbs) < 5 && SpellCooldown("Mind Blast") < 0);
                 Cast("Shadow Word: Pain", () => Me.GetPower(WoWPowerType.PriestShadowOrbs) >= 4 && !Target.HasAura("Shadow Word: Pain") && Target.HealthFraction > 0.2);
                 Cast("Vampiric Touch", () => Me.GetPower(WoWPowerType.PriestShadowOrbs) >= 4 && !Target.HasAura("Vampiric Touch") && Target.HealthFraction > 0.2);
                 Cast("Devouring Plague", () => (Me.GetPower(WoWPowerType.PriestShadowOrbs) >= 5) || (Me.GetPower(WoWPowerType.PriestShadowOrbs) >= 3 && Target.HasAura("Vampiric Touch") && Target.HasAura("Shadow Word: Pain")));
                 Cast("Shadow Word: Death", () => Target.HealthFraction < 0.2);
                 Cast("Mind Flay", () => Me.AuraTimeRemaining("Shadow Word: Insanity") >= 1);
                 Cast("Mind Spike", () => (Target.AuraTimeRemaining("Vampiric Touch") <= 8 && Target.AuraTimeRemaining("Shadow Word: Pain") <= 8) || (Target.AuraTimeRemaining("Vampiric Touch") <= 2 && Target.AuraTimeRemaining("Shadow Word: Pain") <= 2));
                 foreach (var aggro in Adds.Where(x => x.DistanceSquared < SpellMaxRangeSq("Shadow Word: Pain")))
                 {
                     Cast("Shadow Word: Pain", aggro, ()=> !Target.HasAura("Shadow Word: Pain"));
                 }

                 Cast("Mind Sear", Me.Target, () => Adds.Where(x => x.DistanceSquaredTo(Target) < 10 * 10).Count() > 1 && !Me.Target.HasAura("Mind Sear"));
                 Cast("Mind Flay");
                 
             }
             return false;
        }
        


        //--------------Talent Start --------------      
        void DesperatePrayer() // Rotated in
        {
            if (CastPreventDouble("Desperate Prayer", () => Me.HealthFraction < 0.5 && !Me.IsCasting)) return;
        }
        void AngelicFeather() //Rotated in
        {
            if (CastOnTerrain("Angelic Feather", Me.PositionPredicted, () => Me.MovementSpeed > 0 && !HasAura("Angelic Feather"))) return;
        }
        void MindBender() //Rotated in
        {
            if (Cast("Mindbender", () => Me.ManaFraction < 0.5 && Me.Target.IsEnemy, Adds.FirstOrDefault()))
            {
                DebugWrite("Low Mana Casting Mindbender");
            }
        }
        void PowerWordSolace() //Rotated in
        {
            List<UnitObject> mobs = Adds.FindAll(x => x.DistanceSquared < SpellMaxRangeSq("Power Word: Solace") && x.IsEnemy);
            if (mobs.Count > 0)
            {
                //Solace CD Check
                if (SpellCooldown("Power Word: Solace") < 0)
                {

                    //Cast solace on add
                    var Solmob = mobs.FirstOrDefault();
                    CastPreventDouble("Power Word: Solace", () => !Solmob.IsDead && Solmob.IsInCombatRangeAndLoS && Me.Target.IsEnemy, Solmob);
                    DebugWrite("Casting Solace on " + Solmob + SpellCooldown("Power Word: Solace"));
                    return;
                }
            }

            if (Cast("Power Word: Solace")) return;
        }
        void VoidTendrils() //Rotated in
        {
            List<UnitObject> mobs = Adds.FindAll(x => x.DistanceSquaredTo(Target) < 10 * 10);
            if (CastPreventDouble("Void Tendrils", () => mobs.Count > 2, Adds.FirstOrDefault())) return;
        }
        void PsychicScream()
        {
            List<UnitObject> mobs = Adds.FindAll(x => x.DistanceSquaredTo(Me) < 8 * 8);
            if (CastPreventDouble("Psychic Scream", () => mobs.Count > 2)) return;
        }
        void DominateMind()
        {
            //No idea how to get this working at the min :D
        }
        void SpiritShell()
        {
            if (CastPreventDouble("Spirit Shell", () => !Target.IsEnemy && Target.HealthFraction < 0.9 && Target.IsInCombatRangeAndLoS && !Me.HasAura("Spirit Shell"))) return;
        }
        void Cascade()//Rotated in
        {
            List<PlayerObject> members = Group.GetGroupMemberObjects();
            if (members.Count > 0)
            {
                List<PlayerObject> GrpHeal1 = members.FindAll(x => x.HealthFraction <= 0.85 && x.IsInCombatRangeAndLoS && !x.IsDead);
                PlayerObject healtarget = GrpHeal1.FirstOrDefault();
                if (GrpHeal1.Count > 2)
                {
                    if (CastPreventDouble("Cascade", () => Target.HealthFraction < 0.9 && SpellCooldown("Cascade") < 0, healtarget)) return;
                }
            }
        }


        void DivineStar()//Rotated in
        {
            List<PlayerObject> members = Group.GetGroupMemberObjects();
            if (members.Count > 0)
            {
                // Finding Tank
                List<PlayerObject> Tanks = members.FindAll(x => x.IsTank && x.IsInCombatRangeAndLoS && !x.IsDead);
                PlayerObject Tank = Tanks.FirstOrDefault();
                if (Tank != null)
                {
                    Cast("Divine Start", () => !Tank.IsDead && Tank.HealthFraction < 0.8, Tank);
                    return;
                }
            }
        }
        void Halo()// Rotated in
        {
            List<PlayerObject> members = Group.GetGroupMemberObjects();
            if (members.Count > 0)
            {
                List<PlayerObject> GrpHeal1 = members.FindAll(x => x.HealthFraction <= 0.85 && x.IsInCombatRangeAndLoS && !x.IsDead && x.DistanceSquaredTo(Me) < SpellMaxRangeSq("Halo"));
                if (GrpHeal1.Count > 2)
                {
                    if (CastPreventDouble("Halo", () => Target.HealthFraction < 0.9 && SpellCooldown("Halo") < 0)) return;
                }
            }
        }
        //------------Talents End-----------
      
       

    }
}